/* ******************************************************************
 * This file is part of the escal project and distributed under the
 * terms of the GNU General Public License Version 3
 * Copyright (C) 2008 Epocher (xijiaosdq@gmail.com)
 * See COPYING file for licensing information.
 *******************************************************************/

#ifndef FILE_MANAGER_H
#define FILE_MANAGER_H

#include "escal.h"
#include <QBitArray>
#include <QByteArray>
#include <QList>
#include <QMutex>
#include <QDir>
#include <QFile>
#include <QWaitCondition>
#include <QThread>

class QTimer;
class QTextCursor;
class QTextDocument;


class FileManager:public QThread{
	Q_OBJECT
public:
	FileManager(QString folderName, QString fileName, QObject *parent = 0);
	~FileManager();
	bool isNew() const { return newFile ; };
	void checkDigest();
	int initNewFile(const qint64 &fileSize ,bool acceptRange);
	int read(int pieceIndex, qint64 offset, int length);
	int write(int &pieceIndex, qint64 &offset, bool &gotPiece,
			const QByteArray &data);
	int getPieceNum();
	qint64 getFileSize(){ return fileSize; };
	qint64 getFinishedSize(){ return finishedSize; };
	virtual QTextDocument *getTextDocument() { return textDocument ;};
	void remove();
	int getUndonePieceNum();
	int getWorkingPieceNum();
	bool isAcceptRange();
	void setAcceptRange();
	bool hasError() { return error; };
	int getPiece(int formerPieceIndex=-1);
	void releasePiece(int pieceIndex);
signals:
	void fileIsInitialized();
	void fileIsFinished();
	void progressForward();
	void writeLog(QTextCursor *cursor, QString text1, QString text2);
protected:
	QByteArray readBlock(int pieceIndex, qint64 offset, int length);
	bool writeBlock(int pieceIndex, qint64 offset, const QByteArray &data);
	bool setPaths(const QString &folderName, const QString &fileName);
	void cleanUp();
	void run();
	void syncDigest();
	bool loadDigest();
private:
	bool newFile;
	bool quit;
	bool acceptRange;
	bool error;
	bool progressForwarded;
	qint64 fileSize;
	qint64 finishedSize;
	int pieceNum;
	QString folderName;
	QString fileName;
	QString dateString;
	// the file to restore the file info 
	QString digestFileName;
	QFile file;
	QFile digestFile;
	QDir dir;
	QTextCursor *textCursor;
	QTextDocument *textDocument;
	struct WriteRequest {
		int pieceIndex;
		qint64 offset;
		QByteArray data;
	};
	struct ReadRequest {
		int pieceIndex;
		qint64 offset;
		int length;
		int id;
	};
	
	mutable QWaitCondition cond;
	QMutex mutex;
	QBitArray piecesWorking;
	QBitArray piecesDone;
	QList<WriteRequest> writeRequests;
	QList<ReadRequest> readRequests;
};

#endif /* FILE_MANAGER_H */
